﻿using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Options;
using StackExchange.Redis;

namespace PmSoft.Cache.Redis;

/// <summary>
/// Redis 缓存提供者，管理 Redis 连接和数据库访问
/// </summary>
public class RedisCacheProvider : IRedisCacheProvider
{
	private readonly Lazy<ConnectionMultiplexer> _connectionMultiplexer;
	private bool _disposed;

	/// <summary>
	/// 构造函数，初始化 Redis 连接
	/// </summary>
	/// <param name="optionsAccessor">Redis 缓存选项访问器</param>
	public RedisCacheProvider(IOptions<RedisCacheOptions> optionsAccessor)
	{
		Options = optionsAccessor?.Value ?? throw new ArgumentNullException(nameof(optionsAccessor));
		_connectionMultiplexer = new Lazy<ConnectionMultiplexer>(CreateConnectionMultiplexer);
		Database = GetDatabase(Options.ConfigurationOptions?.DefaultDatabase ?? 0);
	}

	/// <summary>
	/// 获取 Redis 数据库实例
	/// </summary>
	public IDatabase Database { get; }

	/// <summary>
	/// 获取 Redis 缓存选项
	/// </summary>
	public RedisCacheOptions Options { get; }

	/// <summary>
	/// 创建 Redis 连接多路复用器
	/// </summary>
	/// <returns>连接多路复用器实例</returns>
	private ConnectionMultiplexer CreateConnectionMultiplexer()
	{
		if (string.IsNullOrEmpty(Options.Configuration))
			throw new ArgumentNullException(nameof(Options.Configuration), "Redis 配置不能为空");
		return ConnectionMultiplexer.Connect(Options.Configuration);
	}

	/// <summary>
	/// 获取指定编号的 Redis 数据库
	/// </summary>
	/// <param name="db">数据库编号</param>
	/// <returns>Redis 数据库实例</returns>
	public IDatabase GetDatabase(int db = 0)
	{
		return _connectionMultiplexer.Value.GetDatabase(db);
	}

	/// <summary>
	/// 释放 Redis 连接资源
	/// </summary>
	public void Dispose()
	{
		if (_disposed) return;

		if (_connectionMultiplexer.IsValueCreated)
		{
			_connectionMultiplexer.Value.Close();
			_connectionMultiplexer.Value.Dispose();
		}

		_disposed = true;
	}
}